package 剑指offer.字符串;

/**
 * 字符串 “+100”、“5e2”、“3.14”、“5e2”、“-1E-16” 都是数值
 * 他们符合以下规则：
 * A.BeC
 * A.BEC
 * <p>
 * .BeC
 * .BEC
 * <p>
 * A 和 C 都表示整数，可以有正负号
 * B 表示小数 不含正负号
 *
 * 现在要求输入一个代表数字的字符串，判断它是否合法
 */
public class 第20题表示数值的字符串 {

    public static int index = 0;

    public static boolean isNumeric(char[] str) {
        if (str == null || str.length == 0) {
            return false;
        }
        // 先处理一开始的数值部分，去除正负号
        boolean res = judgeSymbol(str);

        // 接下来的数据有三种情况

        // 1. index 指向了小数点
        if (index < str.length && str[index] == '.') {
            index++;
            // 处理完小数点后应该立即处理小数点后面的数字
            res = res && judgeSymbol(str);
        }
        // 2. index 指向了 e 或 E
        if (index < str.length && (str[index] == 'e' || str[index] == 'E')) {
            index++;
            // 还是立刻处理数字
            res = res && judgeSymbol(str);
        }
        // 3. index 指向最后，但是可能遇到这类问题：123.45e+6.6，此时的字符串是不合法的，index 指向的是.没有指向末尾
        // 所以要检查index是否指向字符串末尾，是的就代表检查完毕，不是的就代表存在非法字符占用了一次检查，导致index无法指向末尾
        return res && index >= str.length;
    }

    private static boolean judgeSymbol(char[] str) {
        if (index < str.length && (str[index] == '+' || str[index] == '-')) {
            index++;
        }
        // 处理完正负号后，后面的必须是整数，所以应该立刻校验
        return isInteger(str);
    }

    private static boolean isInteger(char[] str) {
        boolean res = false;
        // 上面处理完了正负号，下面就马上检查数字是否合法
        // 注意用 while 循环检查，直到遇到E或者其他字符
        while (index < str.length && (str[index] >= '0' && str[index] <= '9')) {
            index++;
            res = true;
        }
        return res;
    }

    public static void main(String[] args) {
//        char[] str = "+100".toCharArray();
//        char[] str = "+1.00".toCharArray();
//        char[] str = "123.45e+6".toCharArray();
        char[] str = "123.45e+6.6".toCharArray();


        System.out.println(isNumeric(str));
    }
}
